﻿using System;
using System.Collections.Generic;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using FRL.DebtChased.Extensions;
using FRL.DebtChased.Repository;
using FRL.DebtChased.Repository.ViewModels;
using FRL.DebtChased.Types;
using FRL.DebtChased.Website;
using FRL.DebtChased.WebServices;

namespace WebApplication.Finance
{

	/// <summary>
	/// Declaration of CreateAccount
	/// </summary>
	public partial class CreateAccoun : System.Web.UI.Page
	{

		/////////////////////////////////////////////////////////////
		// Constants

		private const string ContextModelTag = "NewAccountModel";

		/////////////////////////////////////////////////////////////
		// Attributes

		private AccountTransport ContextAccount
		{
			get
			{
				return ViewState[ContextModelTag] as AccountTransport;
			}
			set
			{
				ViewState[ContextModelTag] = value;
			}
		}

		private DebtChasedEntities m_ent = null;

		/////////////////////////////////////////////////////////////
		// Event handlers

		protected override void OnPreRender(EventArgs e)
		{

			// Call base-class function
			base.OnPreRender(e);

			// Bind the invoices
			gridInvoice.DataSource = ContextAccount.AccountInvoices;
			gridInvoice.DataBind();

			// Enable/disable controls
			cboValidatedBy.Enabled = chkValidated.Checked;
			txtValidatedAt.Enabled = chkValidated.Checked;

		}

		protected void Page_Load(object sender, EventArgs e)
		{

			// If this is a postback...
			if (this.IsPostBack)
			{
#if DEBUG
				Debug.Assert(ContextAccount != null);
#endif // #if DEBUG

			}
			else
			{
#if DEBUG
				Debug.Assert(ContextAccount == null);
#endif // #if DEBUG

				// Bind my application
				MyApplication myApp = MyApplication.BindMyApplication();

				// Open an entities object
				DebtChasedEntities ent = _safeGetEntities();

				// Create the account transport
				AccountTransport account = new AccountTransport();
				account.AccountInvoices = new List<AccountInvoiceTransport>();
				account.DebtorContacts = new List<ContactTransport>();
				account.Notes = new List<AccountNoteTransport>();
				ContextAccount = account;
				account.DebtorName = "Fred The Debtor";

				// Set controls - client dropdown
				cboClient.BindToDictionary(Client.GetDictionary(ent),13991);
				cboClient_SelectedIndexChanged(null, null);

				// Set controls - currency
				Dictionary<string, string> currencyMap = Money.GetDictionary();
				cboCurrency.BindToDictionary(currencyMap);
				cboCurrency.SelectedValue = Money.CurrencyToCode(Money.eCurrency.Sterling);
				txtNewAmount.Text = "100";

				// Set controls - collector and manager
				cboCollector.BindToDictionary(FRL.DebtChased.Repository.User.GetDictionary(ent, Definitions.AnyFinUserRole, true));
				cboCollector.SelectedIndex = 0;
				cboManager.BindToDictionary(FRL.DebtChased.Repository.User.GetDictionary(ent, Definitions.AllFinExceptUserAndSales, true));
				cboManager.SelectedIndex = 0;

				// Set controls - trading styles
				cboTradingStyle.BindToDictionary(AccountTradingStyle.GetDictionary(ent,true), 0);
				cboTradingStyle.SelectedIndex = 0;

				// Set controls - validated
				chkValidated.Checked = true;
				cboValidatedBy.BindToDictionary(FRL.DebtChased.Repository.User.GetDictionary(ent, Definitions.AnyFinUserRole, false));
				calValidatedAt.SelectedDate = DateTime.Now.Date;

				// Set controls - status
				cboNewStatus.BindToDictionary(AccountInvoiceStatus.GetDictionary(ent, true));
				cboNewStatus.SelectedIndex = 0;

				// Set controls - workflow
				cboNewWorkflow.BindToDictionary(Workflow.GetDictionary(ent, true, Definitions.None));
				cboNewWorkflow.SelectedIndex = 0;

				// Set controls - invoice number
				txtNewInvoiceNo.Text = string.Format("{0}", new Random().Next(1000, 10000));

				// Set controls - invoice date
				DateTime dtNow = DateTime.Now;
				txtNewDate.Text = string.Format("{0:dd-MMM-yyyy}", dtNow);

				// Update controls
				txtDebtorName.Text = account.DebtorName;

				// Generate references
				butRandomFRLReference_Click(null, null);
				butRandomClientReference_Click(null, null);

				// Set controls - New Invoice
				calNewDate.SelectedDate = DateTime.Now.Date;

				// Debtor name and client-debtor-ref
				txtDebtorName.Text = "Stephens Ltd";
				txtDebtorClientRef.Text = Extensions.MakeRandomString("XXXXXXXX");

				// Set debtor controls
				txtTitle.Text = "Dr.";
				txtFirstName.Text = "Toby";
				txtInitials.Text = "X";
				txtSurname.Text = "Stephens";
				txtAddressLineA.Text = "Unit 12B";
				txtAddressLineB.Text = "Flower Mews";
				txtCity.Text = "Langley";
				txtCounty.Text = "Berks";
				txtPostcode.Text = "SL5 2TR";
				cboCountryCode.BindToDictionary(CountryCodes.Dictionary);
				cboCountryCode.SelectedValue = myApp.LocationCountryCode;
				txtPhone1.Text = "01344 716 185";
				txtMobile1.Text = "07956 888271";
				txtEmail1.Text = "richardpsalmon@hotmail.com";

				// Set panel colors
				pnlDetails.BackColor = myApp.PrimaryWebColor;
				pnlOptions.BackColor = myApp.PrimaryWebColor;
				pnlInvoices.BackColor = myApp.PrimaryWebColor;
				pnlDebtor.BackColor = myApp.PrimaryWebColor;

			}

		}

		protected void gridInvoice_RowDataBound(object sender, GridViewRowEventArgs e)
		{

			// If this is a data row...
			if (e.Row.RowType == DataControlRowType.DataRow)
			{

				// Get the account invoice
				AccountInvoiceTransport inv = e.Row.DataItem as AccountInvoiceTransport;

				// Date
				TableCell cell = e.Row.Cells[0];
				cell.Text = string.Format("{0:dd-MMM-yyyy}", inv.InvoiceDate);

				// Amount
				cell = e.Row.Cells[2];
				cell.Text = new Money(inv.Amount).ToString();

				// Status
				cell = e.Row.Cells[3];
				if (inv.Status == 0)
					cell.Text = "[none]";
				else
				{
					cell.Text = AccountInvoiceStatus.GetName(_safeGetEntities(), inv.Status);
				}

				// Workflow
				cell = e.Row.Cells[4];
				if (inv.WorkflowId == 0)
					cell.Text = "[none]";
				else
				{
					cell.Text = Workflow.GetName(_safeGetEntities(), inv.WorkflowId);
				}

			}

		}

		protected void gridInvoice_RowCommand(object sender, GridViewCommandEventArgs e)
		{

			// Check the grid view object
			GridView gridView = sender as GridView;
#if DEBUG
			System.Diagnostics.Trace.Assert(gridView == gridInvoice);
#endif // #if DEBUG

			// Get row index
			int iRow = int.Parse(e.CommandArgument.ToString());

			// Convert argument to id
			int iInvoiceId = int.Parse(gridInvoice.DataKeys[iRow].Value.ToString());

			// Compare commands
			if (e.CommandName == "DeleteInvoice")
			{

				// Delete the invoice
				AccountTransport account = ContextAccount;
#if DEBUG
				bool bFound = false;
#endif // #if DEBUG
				for (int i1 = 0; i1 < account.AccountInvoices.Count; i1++)
				{
					if (account.AccountInvoices[i1].AccountInvoiceId == iInvoiceId)
					{
#if DEBUG
						bFound = true;
#endif // #if DEBUG
						account.AccountInvoices.RemoveAt(i1);
						break;
					}
				}
#if DEBUG
				Debug.Assert(bFound);
#endif // #if DEBUG

			}

		}

		protected void butAdd_Click(object sender, EventArgs e)
		{

			// Get the date
			DateTime dt;
			if (!DateTime.TryParse(txtNewDate.Text, out dt))
			{
				(Page.Master as FinanceMaster).ErrorMessage = "Invalid date";
				return;
			}

			// Get the amount
			decimal dcAmount;
			if (!decimal.TryParse(txtNewAmount.Text, out dcAmount))
			{
				(Page.Master as FinanceMaster).ErrorMessage = "Invalid amount";
				return;
			}

			// Get the model
			AccountTransport account = ContextAccount;

			// Create a new invoice
			AccountInvoiceTransport newInvoice = new AccountInvoiceTransport();
			newInvoice.InvoiceNo = txtNewInvoiceNo.Text;
			newInvoice.Amount = new CurrencyTransport()
			{
				Amount = dcAmount,
				CurrencyCode = cboCurrency.SelectedValue.ToString()
			};
			newInvoice.InvoiceDate = dt;

			newInvoice.Status = int.Parse(cboNewStatus.SelectedValue);

			newInvoice.WorkflowId = int.Parse(cboNewWorkflow.SelectedValue);
			if (newInvoice.WorkflowId == 0)
			{
				newInvoice.WorkflowId = 0;
				newInvoice.WorkflowDay1 = null;
			}
			else
			{
				newInvoice.WorkflowDay1 = DateTime.Now;
			}

			// Get the next invoice id
			int iInvoiceId = 0;
			foreach (AccountInvoiceTransport inv in account.AccountInvoices)
				iInvoiceId = Math.Min(iInvoiceId, inv.AccountInvoiceId);
			iInvoiceId--;
			newInvoice.AccountInvoiceId = iInvoiceId;

			// Add to the modelz
			account.AccountInvoices.Add(newInvoice);

			// Increment the amount and the invoice number
			txtNewAmount.Text = (dcAmount + 1).ToString();
			int iInvoiceNumber;
			if (!int.TryParse(txtNewInvoiceNo.Text, out iInvoiceNumber))
				iInvoiceNumber = 1234;
			iInvoiceNumber++;
			txtNewInvoiceNo.Text = iInvoiceNumber.ToString();

		}

		protected void butSave_Click(object sender, EventArgs e)
		{

			// Get the account
			AccountTransport account = ContextAccount;

			// Update model - primary client contact
			account.PrimaryClient = new AccountPrimaryClientTransport();
			account.PrimaryClient.ClientId = int.Parse(cboClient.SelectedValue);
			account.PrimaryClient.PrimaryContact = new ContactTransport();
			account.PrimaryClient.PrimaryContact.ContactId = int.Parse(cboClientContact.SelectedValue);		

			// Update collector and manager
			account.CollectorId = int.Parse(cboCollector.SelectedValue);
			account.ManagerId = int.Parse(cboManager.SelectedValue);

			// Debtor name
			account.DebtorName = txtDebtorName.Text;

			// FRL and client reference
			account.FRLReference = txtFRLReference.Text;
			account.ClientReference = txtClientReference.Text;
			account.DebtorClientRef = txtDebtorClientRef.Text;

			// If validated...
			if (chkValidated.Checked)
			{
				account.ValidatedAt = new DateTime(
					calValidatedAt.SelectedDate.Value.Year,
					calValidatedAt.SelectedDate.Value.Month,
					calValidatedAt.SelectedDate.Value.Day,
					DateTime.Now.Hour,
					DateTime.Now.Minute,
					DateTime.Now.Second
				);
				account.ValidatedBy = int.Parse(cboValidatedBy.SelectedValue);
			}
			else
			{
				account.ValidatedAt = null;
				account.ValidatedBy = 0;
			}

			// Build a contact for the debtor
			ContactTransport contact = new ContactTransport();
			contact.AddressList = new List<ContactAddressTransport>();
			contact.PointList = new List<ContactPointTransport>();
			contact.Title = txtTitle.Text;
			contact.FirstName = txtFirstName.Text;
			contact.Initials = txtInitials.Text;
			contact.Surname = txtSurname.Text;
			contact.DOB = new DateTime(1960, 3, 4);

			ContactAddressTransport addr = new ContactAddressTransport();
			contact.AddressList.Add(addr);
			addr.AddressLineA = txtAddressLineA.Text;
			addr.AddressLineB = txtAddressLineB.Text;
			addr.City = txtCity.Text;
			addr.County = txtCounty.Text;
			addr.Postcode = txtPostcode.Text;
			addr.AddressType = (int)Definitions.eContactAddressType.Default;				

			if (!string.IsNullOrEmpty(txtPhone1.Text))
				contact.PointList.Add(new ContactPointTransport() { ContactPointType = (int)Definitions.eContactPointType.Phone, Address = txtPhone1.Text, ContactPointStatus = (int)Definitions.eContactPointStatus.NotSet });

			if (!string.IsNullOrEmpty(txtPhone2.Text))
				contact.PointList.Add(new ContactPointTransport() { ContactPointType = (int)Definitions.eContactPointType.Phone, Address = txtPhone2.Text, ContactPointStatus = (int)Definitions.eContactPointStatus.NotSet });

			if (!string.IsNullOrEmpty(txtFax1.Text))
				contact.PointList.Add(new ContactPointTransport() { ContactPointType = (int)Definitions.eContactPointType.Fax, Address = txtFax1.Text, ContactPointStatus = (int)Definitions.eContactPointStatus.NotSet });

			if (!string.IsNullOrEmpty(txtMobile1.Text))
				contact.PointList.Add(new ContactPointTransport() { ContactPointType = (int)Definitions.eContactPointType.Mobile, Address = txtMobile1.Text, ContactPointStatus = (int)Definitions.eContactPointStatus.NotSet });

			if (!string.IsNullOrEmpty(txtMobile2.Text))
				contact.PointList.Add(new ContactPointTransport() { ContactPointType = (int)Definitions.eContactPointType.Mobile, Address = txtMobile2.Text, ContactPointStatus = (int)Definitions.eContactPointStatus.NotSet });

			if (!string.IsNullOrEmpty(txtEmail1.Text))
				contact.PointList.Add(new ContactPointTransport() { ContactPointType = (int)Definitions.eContactPointType.Email, Address = txtEmail1.Text, ContactPointStatus = (int)Definitions.eContactPointStatus.NotSet });

			if (!string.IsNullOrEmpty(txtEmail2.Text))
				contact.PointList.Add(new ContactPointTransport() { ContactPointType = (int)Definitions.eContactPointType.Email, Address = txtEmail2.Text, ContactPointStatus = (int)Definitions.eContactPointStatus.NotSet });

			// Add contact to account
			account.DebtorContacts.Clear();
			account.DebtorContacts.Add(contact);

			// Get the user id
			int iUserId = MySession.BindMySession().UserID;
#if DEBUG
			if (iUserId == 0)
				iUserId = 1;
#endif // #if DEBUG

			// Declare an entities object
			DebtChasedEntities ent = _safeGetEntities();

			// Save the new account
			List<string> Error = Account.AddNew(ent, account, iUserId);
			if (Error.Count == 0)
				this.Reload();
			else
				(Page.Master as FinanceMaster).ErrorMessage = Error.Join("<br>");

		}

		protected void cboClient_SelectedIndexChanged(object sender, EventArgs e)
		{

			// Load the contacts for this client
			int iClientId = int.Parse(cboClient.SelectedValue);
			Dictionary<int,string> clientContactMap = ClientContact.LoadContactDictionary(_safeGetEntities(), iClientId);
			cboClientContact.BindToDictionary(clientContactMap);
			cboClientContact.SelectedIndex = 0;

		}

		protected void butRandomFRLReference_Click(object sender, EventArgs e)
		{

			// Generate a random FRL reference
			txtFRLReference.Text = string.Format("FRL{0}", Extensions.MakeRandomString("XXXXXXXX"));

		}

		protected void butRandomClientReference_Click(object sender, EventArgs e)
		{

			// Generate a random FRL reference
			txtClientReference.Text = Extensions.MakeRandomString("XXXXXXXX");

		}

		/////////////////////////////////////////////////////////////
		// Operations

		private DebtChasedEntities _safeGetEntities()
		{

			// If object needs declaring...
			if (m_ent == null)
				m_ent = new DebtChasedEntities();

			// Return reference
			return m_ent;

		}

	}

}